//---------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------//
//   Model
//---------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------//
#include "Model.h"
#include "Base/Logger.h"
#include "ImageManager.h"
#include <string>
#include <iostream>
#include <fstream>

//---------------------------------------------------------------------------------------------------//
Model::Model()
{
    loadModel("Data/tileGrass.mdl");
    reset();
    mpt_delay = 0.12;
	mpt_isLoop = true;
	mpt_visible = true;
	stop();
	mpt_currentGroup = "None";
}
//---------------------------------------------------------------------------------------------------//
Model::Model(const std::string& filename)
{
    loadModel(filename);

    reset();
    mpt_delay = 0.12;
	mpt_isLoop = true;
	mpt_visible = true;
	stop();
	if(!mpt_groups.empty())
	{
		mpt_currentGroup = mpt_groups.begin()->first;
		play();
	}
}
//---------------------------------------------------------------------------------------------------//
Model::~Model()
{

}
//---------------------------------------------------------------------------------------------------//
bool Model::loadModel(const std::string& filename)
{
    std::ifstream f;
    f.open(filename.c_str(), std::ios::in);
	if (!f)
	{
		std::cout<<"Couldn't open the model file : "<<filename.c_str()<<std::endl;
		return false;
	}

    std::string str;
    if(f >> str && str != "[MODEL]")
    {
        std::cout<<"Bad model file"<<std::endl;
        return false;
    }
	while(f >> str && str != "")
	{
		if(str == "FILE")
		{
		    f >> str;
		    sf::Texture* img = ImageManager::getSingletonPtr()->GetImage(str);
            if(img)
            {
                mpt_sprite.setTexture(*img);
            }
        }
        else if(str == "FRAME")
        {
			Frame tempFrame;
            unsigned int index;
			
            f >> index;
            f >> tempFrame.center.x;
            f >> tempFrame.center.y;
            f >> tempFrame.subrect.left;
            f >> tempFrame.subrect.top;
            f >> tempFrame.subrect.width;
            f >> tempFrame.subrect.height;
			
            mpt_frames[index] = tempFrame;
        }
        else if(str == "GROUP")
        {
            f >> str;
            sf::Vector2i frame;
            f >> frame.x;
            f >> frame.y;
            addGroup(str, frame);
        }
	}
	f.close();

	reset();

	return true;
}
//---------------------------------------------------------------------------------------------------//
sf::Sprite Model::getCurrentSprite() const
{
	if(mpt_visible)
	{	
		return mpt_sprite;
	}
	else
	{
		sf::Sprite sprite(mpt_sprite);
		sprite.setColor(sf::Color(0,0,0,0));
		return sprite;
	}
}
//---------------------------------------------------------------------------------------------------//
void Model::flipX(bool flip)
{
	//mpt_sprite.flipX(flip);
	/*if(flip)
		mpt_sprite.setScale(sf::Vector2f(-1, 0));
	else
		mpt_sprite.setScale(sf::Vector2f(1, 0));*/
}
//---------------------------------------------------------------------------------------------------//
void Model::setSpriteRotation(float angle)
{
	mpt_sprite.setRotation(angle);
}
//---------------------------------------------------------------------------------------------------//
void Model::setSpriteCenter(const sf::Vector2f& center)
{
    mpt_sprite.setOrigin(center);
}
//---------------------------------------------------------------------------------------------------//
void Model::setSpritePosition(const sf::Vector2f& position)
{
    mpt_sprite.setPosition(position);
}
//---------------------------------------------------------------------------------------------------//
void Model::setSpriteSubRect(const sf::IntRect& subrect)
{
    mpt_sprite.setTextureRect(subrect);
}
//---------------------------------------------------------------------------------------------------//
void Model::changeFrame(unsigned int frame)
{
    if(mpt_frames.find(frame) != mpt_frames.end())
    {
        setSpriteSubRect(mpt_frames[frame].subrect);
        setSpriteCenter(mpt_frames[frame].center);

        mpt_frameCount = frame;
    }
}
//---------------------------------------------------------------------------------------------------//
void Model::nextFrame()
{
    if(currentFrame()>= getSize()-1)
    {
        changeFrame(0);
        if(!isLoop())
            stop();
    }
    else
		changeFrame(currentFrame()+1);
}
//---------------------------------------------------------------------------------------------------//
void Model::reset()
{
    stop();
	play();
}
//---------------------------------------------------------------------------------------------------//
unsigned int Model::currentFrame() const
{
    return mpt_frameCount;
}
//---------------------------------------------------------------------------------------------------//
void Model::loop(bool choice)
{
    mpt_isLoop=choice;
}
//---------------------------------------------------------------------------------------------------//
bool Model::isLoop() const
{
    return mpt_isLoop;
}
//---------------------------------------------------------------------------------------------------//
void Model::play()
{
    mpt_play = true;
	mpt_clock.Start();
}
//---------------------------------------------------------------------------------------------------//
void Model::stop()
{
    mpt_play = false;
    changeFrame(mpt_frames.begin()->first);
    mpt_clock.Reset(true);
}
//---------------------------------------------------------------------------------------------------//
void Model::stopGroup()
{
    if(mpt_groups.find(mpt_currentGroup) != mpt_groups.end())
    {
        stop();
        changeFrame(mpt_groups.find(mpt_currentGroup)->second.x);
    }
}
//---------------------------------------------------------------------------------------------------//
void Model::pause()
{
    mpt_play = false;
    mpt_clock.Pause();
}
//---------------------------------------------------------------------------------------------------//
bool Model::isPlaying() const
{
    return mpt_play;
}
//---------------------------------------------------------------------------------------------------//
void Model::setDelay(const float &delay)
{
    mpt_delay = delay;
}
//---------------------------------------------------------------------------------------------------//
float Model::delay() const
{
    return mpt_delay;
}
//---------------------------------------------------------------------------------------------------//
void Model::update()
{
    if(isPlaying())
	{
		if(delay())
		{
			unsigned int frameCount = (unsigned int)(mpt_clock.GetElapsedTime()/delay());
			if(!isLoop() && frameCount>getSize()  && getGroup() == "None")
				stop();
            else if(!isLoop() && getGroup() != "None" && frameCount>mpt_groups.find(getGroup())->second.y - mpt_groups.find(getGroup())->second.x)
                changeFrame(mpt_groups.find(getGroup())->second.x);
			else
			{
				if(getGroup() == "None")
                    frameCount = frameCount % getSize();
                else
                    frameCount = frameCount % (mpt_groups.find(getGroup())->second.y - mpt_groups.find(getGroup())->second.x + 1) + mpt_groups.find(getGroup())->second.x;
				changeFrame(frameCount);
			}
		}
		else nextFrame();
	}
}
//---------------------------------------------------------------------------------------------------//
unsigned int Model::getSize()
{
    return mpt_frames.size();
}
//---------------------------------------------------------------------------------------------------//
void Model::setGroup(const std::string& group)
{
    if(mpt_groups.find(group) != mpt_groups.end() && mpt_currentGroup != group)
    {
        mpt_currentGroup = group;
        stop();
		play();
        changeFrame(mpt_groups.find(group)->second.x);
    }
    else if(mpt_currentGroup != group)
    {
        mpt_currentGroup = "None";
        stop();
    }
}
//---------------------------------------------------------------------------------------------------//
const std::string& Model::getGroup() const
{
    return mpt_currentGroup;
}
//---------------------------------------------------------------------------------------------------//
void Model::addGroup(const std::string& name, const sf::Vector2i& frames)
{
    mpt_groups[name] = frames;
}
//---------------------------------------------------------------------------------------------------//
void Model::setVisible(bool visible)
{
	mpt_visible = visible;
}
